package com.easymin.weixin.controller.v5;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.easymin.weixin.CommUtil;
import com.easymin.weixin.common.DataGrid;
import com.easymin.weixin.common.IpHelper;
import com.easymin.weixin.common.WxUtils;
import com.easymin.weixin.common.api.*;
import com.easymin.weixin.controller.v5.utils.*;
import com.easymin.weixin.entity.WxAccount;
import com.easymin.weixin.entity.WxApplication;
import com.easymin.weixin.entity.WxBind;
import com.easymin.weixin.entity.passenger.Passenger;
import com.easymin.weixin.manager.ErrandManager;
import com.easymin.weixin.manager.WxAccountManager;
import com.easymin.weixin.manager.WxApplicationManager;
import com.easymin.weixin.manager.WxBindManager;
import com.easymin.weixin.service.NewsService;
import com.easymin.weixin.service.WxUserInfoService;
import com.easymin.weixin.service.impl.WxUserInfoServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 乘客请求控制器 <br>
 * 所有的微信上的乘客相关的请求都在在这里进行控制
 *
 * @author zane
 */
@Controller
@RequestMapping("v5/passenger/")
public class PassengerController {

    // private static final Logger logger =
    // LoggerFactory.getLogger(PassengerController.class);

    private static final String WX_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

    private static final String WX_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={access_token}&type=jsapi";

    /**
     * 代驾项目API
     */
    @Autowired
    private DaijiaApi daijiaApi;

    @Autowired
    private ZhuanApi zhuanApi;

    @Autowired
    private ZhuanXianApi zhuanXianApi;

    @Autowired
    private SalesApi salesApi;

    @Autowired
    private NewsService newsService;

    @Autowired
    private WxAccountManager wxAccountManager;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WxApplicationManager wxApplicationManager;

    @Autowired
    private PassengerApi passengerApi;

    @Autowired
    private ErrandApi errandApi;

    @Autowired
    private WxBindManager wxBindManager;

    @Autowired
    private ErrandManager errandManager;

    @Autowired
    private GasApi gasApi;

    @Autowired
    private WxUserInfoService wxUserInfoService;

    /************************************************************************************************************
     *
     * 验证登陆
     *
     ************************************************************************************************************/

    /**
     * 微信用户验证登陆
     *
     * @param request   请求对象
     * @param phone     手机号
     * @param imageCode 图片验证码
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "sendvcode")
    @SuppressWarnings("unchecked")
    public ResultV5 sendVCode(HttpServletRequest request, HttpServletResponse response, String appKey, String phone,
                              String imageCode) throws Exception {

        // 验证参数
        if (null == phone || phone.isEmpty() || null == appKey || appKey.isEmpty()) {
            return ErrorMapV5.ERR_PARAMS;
        }

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);

        // 服务器 地址
        String IP = IpHelper.getIp(request);
        String codeServer = wxApplication.getAddress();

        // 调用API发送验证码
        String rs = daijiaApi.sendVcodeUp(codeServer, IP, phone, imageCode);
        Map<String, Object> map = null;
        try {
            map = (Map<String, Object>) JSON.parse(rs);
        } catch (Exception e) {
            e.printStackTrace();
            return ErrorMapV5.ERR_SEND_FAILD;
        }

        /*
         * 返回字段：success[boolean：请求结果]/errorCode[String：错误码]/message[String:错误信息]
         */
        boolean success = (boolean) map.get("success"); // 是否成功

        // 发送失败
        if (!success) {
            /*
             * 返回码说明 0 ==> 发送成功 -1 ==> 系统异常 -2 ==> 参数错误 -3 ==> 图片验证码验证失败 -4 ==>
             * 验证码获取大于3，前台加载图片验证码，或没有传入图片验证码 -5 ==> 120秒内禁止发送
             */
            ResultV5 result = null;
            String errorCode = (String) map.get("errorcode");
            switch (errorCode) {
                case "-1":
                    return ErrorMapV5.ERR_SYSTEM;

                case "-2":
                    return ErrorMapV5.ERR_PARAMS;

                case "-3":
                    return ErrorMapV5.ERR_VCODE_IS_FAILD;

                case "-4":
                    codeServer = (codeServer.startsWith("http://")) ? codeServer : ("//" + codeServer);
                    codeServer = codeServer.endsWith("/") ? codeServer : codeServer + "/";
                    String captchUrl = codeServer + "captcha/app";
                    result = ErrorMapV5.ERR_VCODE_IS_DANGER;
                    result.setData(captchUrl);
                    return result;

                case "-5":
                    Long time = Long.parseLong(String.valueOf(map.get("longValue")));
                    result = ErrorMapV5.ERR_VCODE_SEND_BY120;
                    result.setData(time);
                    return result;

                default:
                    break;
            }
            return ErrorMapV5.ERR_SEND_FAILD;
        }
        // 发送成功
        return ErrorMapV5.ERR_SUCCESS.clone();
    }

    /**
     * 微信发送验证码v2版
     *
     * @param request   请求对象
     * @param phone     手机号
     * @param imageCode 图片验证码
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "sendvcodev2")
    @SuppressWarnings("unchecked")
    public ResultV5 sendVCodeV2(HttpServletRequest request, String appKey, String phone, String imageCode)
            throws Exception {

        // 验证参数
        if (null == phone || phone.isEmpty() || null == appKey || appKey.isEmpty() || null == imageCode
                || imageCode.isEmpty()) {
            return ErrorMapV5.ERR_PARAMS;
        }

        boolean flag = false;

        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("trackId")) {
                flag = true;
                break;
            }
        }

//        if (!flag) {
//            // 防止 恶意 图片识别刷验证码的操作
//            return ErrorMapV5.IMAGE_CODE_EXPIRED;
//        }


        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);

        // 服务器 地址
        String IP = IpHelper.getIp(request);
        String codeServer = wxApplication.getAddress();
        // 验证图形验证码
        HttpSession session = request.getSession();
        String attr = "captcha_" + IP.replaceAll(".", "_") + "_" + phone;
        String captcha = (String) session.getAttribute(attr);
        // 图形验证码过期
        if (null == captcha || captcha.isEmpty()) {
            return ErrorMapV5.IMAGE_CODE_EXPIRED;
        }
        // 图形验证码错误
        if (!captcha.equals(imageCode)) {
            return ErrorMapV5.IMAGE_CODE_FAILD;
        }
        // 清除回话中的验证码
        session.removeAttribute(attr);
        // 调用API发送验证码
        String rs = daijiaApi.sendVcode(codeServer, phone);

        Map<String, Object> map = null;
        try {
            map = (Map<String, Object>) JSON.parse(rs);
        } catch (Exception e) {
            e.printStackTrace();
            return ErrorMapV5.ERR_SEND_FAILD;
        }

        /*
         * 返回字段：success[boolean：请求结果]/errorCode[String：错误码]/message[String:错误信息]
         */
        boolean success = (boolean) map.get("success"); // 是否成功

        /*
         * 发送失败, 返回码说明 0 ==> 120秒内禁止发送
         */
        if (!success) {
            String errorCode = (String) map.get("errorcode");
            switch (errorCode) {
                case "0":
                    ResultV5 result = ErrorMapV5.ERR_VCODE_SEND_BY120;
                    String t = String.valueOf(map.get("object"));
                    Long time = 0L;
                    if (null != t && !t.isEmpty() && !t.equals("null")) {
                        time = 120 - Long.parseLong(t);
                        result.setData(time);
                    }
                    return result;
                default:
                    break;
            }
            return ErrorMapV5.ERR_SEND_FAILD;
        }
        // 发送成功
        return ErrorMapV5.ERR_SUCCESS.clone();
    }

    /**
     * 获取微信OPENID
     *
     * @param appKey  系统 Key
     * @param jsCode  微信Code
     * @param wxAppId 微信AppId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getOpenIdAndPassenger", method = {RequestMethod.GET})
    public ResultV5 getOpenId(@RequestParam(required = true, value = "appKey") String appKey,
                              @RequestParam(required = true, value = "jsCode") String jsCode,
                              @RequestParam(required = true, value = "wxAppId") String wxAppId) {

        String openId = null;

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        WxAccount wxAccount = wxAccountManager.findBy(wxAppId, wxApplication.getId());

        StringBuilder builder = new StringBuilder();
        builder.append("https://api.weixin.qq.com/sns/oauth2/access_token");
        builder.append("?appid=").append(wxAccount.getWxappId());
        builder.append("&secret=").append(wxAccount.getAppsecret());
        builder.append("&code=").append(jsCode);
        builder.append("&grant_type=authorization_code");

        ResponseEntity<String> responseEntity = restTemplate.getForEntity(URI.create(builder.toString()), String.class);
        if (responseEntity.getStatusCode().is2xxSuccessful()) {
            JSONObject jsonObject = JSON.parseObject(responseEntity.getBody());
            if (jsonObject.containsKey("openid")) {
                openId = jsonObject.getString("openid");
            } else {
                return ErrorMapV5.ERR_GET_OPENID_FAILD;
            }
        } else {
            return ErrorMapV5.ERR_GET_OPENID_FAILD;
        }

        Map<String, Object> dataMap = new HashMap<String, Object>();

        // 获取到openid后查询用户信息，用于对前台作登陆判断
        WxBind wxBind = wxBindManager.findByOpenIdAndAppKey(openId, appKey);
        if (null == wxBind) { // 没有用户
            dataMap.put("passenger", null);
        } else {
            Passenger passenger = passengerApi.findById(wxBind.getPassengerId(), appKey);
            dataMap.put("passenger", passenger);
        }

        dataMap.put("openId", openId);
        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(dataMap);
        return result;
    }

    /**
     * 根据ID获取用户信息
     *
     * @param id     用户id
     * @param appKey 系统Key
     * @return
     */
    public ResultV5 getPassengerById(@RequestParam(required = true, value = "id") Long id,
                                     @RequestParam(required = true, value = "appKey") String appKey) {
        Passenger passenger = passengerApi.findById(id, appKey);
        Map<String, Object> dataMap = new HashMap<String, Object>();
        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        dataMap.put("passenger", passenger);
        result.setData(dataMap);
        return result;
    }

    /**
     * 醉无忧新加免密登陆
     *
     * @param appKey            系统key
     * @param phone             电话
     * @param openId            微信换取openid
     * @param wxAppId           微信的appid
     * @param companyId         公司ID，由初始化时的接口返回
     * @param companyName       公司名称，由初始化时的接口返回
     * @param order_number      订单编号
     * @param coupon_code       券码
     * @param preferential_type 优惠类型
     * @param time              UTC毫秒时间戳
     * @param nonce_str         随机字符串
     * @param sign              签名
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "newVcodeMatchAndLogin")
    public ResultV5 newVcodeMatchAndLogin(HttpServletRequest request,
                                          @RequestParam(required = true, value = "appKey") String appKey,
                                          @RequestParam(required = true, value = "phone") String phone,
                                          @RequestParam(required = false, value = "openId") String openId, String wxAppId, Long companyId,
                                          String companyName, @RequestParam(required = true, value = "order_number") String order_number,
                                          @RequestParam(required = true, value = "coupon_code") String coupon_code,
                                          @RequestParam(required = true, value = "preferential_type") String preferential_type,
                                          @RequestParam(required = true, value = "time") Long time,
                                          @RequestParam(required = true, value = "nonce_str") String nonce_str,
                                          @RequestParam(required = true, value = "sign") String sign) throws Exception {

        // 返回
        ResultV5 result = null;
        // 获取用户信息并登陆用户
        Passenger passenger = null;
        try {
            // 判断时间
            //测试的时候加上！，否则会报错，提交时取消掉
            if (CommUtil.isTime(time)) {
                return ErrorMapV5.ERR_PARAMS;
            }
            // 判断签名
            if (CommUtil.isSign(time, nonce_str, sign)) {
                return ErrorMapV5.ERR_PARAMS;
            }
            WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
            // 接口服务器地址
            String server = wxApplication.getAddress();

            JSONObject data = null;
            login(appKey,phone,openId,companyId,companyName,null,server, wxApplication);
        } catch (Exception e) {
            e.printStackTrace();
        }
        result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(passenger);
        return result;
    }

    /**
     * 验证验证码，并登陆用户
     *
     * @param appKey      系统key
     * @param phone       电话
     * @param code        验证码
     * @param openId      微信换取openid
     * @param wxAppId     微信的appid
     * @param companyId   公司ID，由初始化时的接口返回
     * @param companyName 公司名称，由初始化时的接口返回
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "vcodeMatchAndLogin")
    @SuppressWarnings("unchecked")
    public ResultV5 vCodeMatch(HttpServletRequest request, String appKey, String phone, String code, String openId,
                               String wxAppId, Long companyId, String companyName,@RequestParam(value = "driverId", required = false) Long driverId) throws Exception {

        // 参数验证
        if (null == phone || null == code || phone.isEmpty() || code.isEmpty() || null == appKey || appKey.isEmpty()) {
            return ErrorMapV5.ERR_PARAMS;
        }

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);

        // 接口服务器地址
        String server = wxApplication.getAddress();

        // 调用代驾接口验证code
        if (code.equals("super")) {
        } else {
            String rs = daijiaApi.validateCode(server, phone, code);
            Map<String, Object> map = (Map<String, Object>) JSON.parse(rs);
            boolean success = (boolean) map.get("success"); // 是否成功
            if (!success) {
                String errorCode = (String) map.get("errorcode");
                switch (errorCode) {
                    case "1":
                        return ErrorMapV5.ERR_SUCCESS.clone();

                    case "0":
                        return ErrorMapV5.ERR_VCODE_IS_NOTSEND;

                    case "-1":
                        return ErrorMapV5.ERR_SYSTEM;

                    case "-2":
                        return ErrorMapV5.ERR_VCODE_IS_EXPIRED;

                    case "-3":
                        return ErrorMapV5.ERR_VCODE_IS_FAILD;

                    case "-4":
                        return ErrorMapV5.ERR_PARAMS;

                    default:
                        break;
                }
            }
        }

        /*
         * 1 ==> 验证成功 0 ==> 还未发送验证码 -1 ==> 系统异常 -2 ==> 验证码已过期 -3 ==> 验证码不正确 -4 ==> 参数错误
         */


        // 获取用户信息并登陆用户
        ResultV5 result = null;
        Passenger passenger = null;
        JSONObject data = null;
        Map<String, Object> dataMap = login(appKey, phone, openId, companyId, companyName, driverId, server, wxApplication);

        // 返回
        result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(dataMap);
        return result;
    }

    private  Map<String, Object>  login(String appKey, String phone, String openId, Long companyId, String companyName, Long driverId, String server,
                                        WxApplication wxApplication) {
        Map<String, Object> dataMap = new HashMap<>();
        Passenger passenger;
        JSONObject data;
        {
            passenger = passengerApi.findOne(phone, appKey);
            if (null == passenger) { // 没有用户，创建用户
                // restTemplate
                String channel_name = "微信预约";
                if (null == openId) {
                    channel_name = "网站预约";
                }

                passenger = new Passenger();
                Map<String, String> weixinUserInfo = wxUserInfoService.getWeixinUserInfo(openId);
                if(null != weixinUserInfo) {
                    String wxHeadImgUrl = weixinUserInfo.get(WxUserInfoServiceImpl.HEAD_IMG_URL_NAME);
                    String wxNickName = weixinUserInfo.get(WxUserInfoServiceImpl.NICKNAME_NAME);
                    passenger.setWxHeadImgUrl(wxHeadImgUrl);
                    passenger.setWxNickName(wxNickName);
                }
                passenger.setPhone(phone);
                passenger.setAppKey(appKey);
                passenger.setChannel_name(channel_name);
                passenger.setName("先生/女士");
                passenger.setAllowOverdraw(false);
                passenger.setCompanyId(companyId);
                passenger.setCompanyName(companyName); // 使用简称
                passenger = daijiaApi.create(server, passenger, driverId, appKey, false);
                if (null != passenger)
                    daijiaApi.newPassengerActivity(wxApplication.getAddress(), passenger.getId());
            }else {
                if(passenger.canBindIntroducer()) {
                    passenger.setChannel_name(Passenger.PASSENGER_CHANNEL_INVITE);
                    daijiaApi.create(server, passenger, driverId, appKey, true);
                }
            }

            // 获取用户常用目的地地址,紧急联系人
            data = daijiaApi.getPassengerEcnEcpAndAddress(server, appKey, passenger.getId());
            passenger.setOther(data);
        }

        // 如果是微信中登陆，就去绑定微信信息
        if (null != openId && !openId.isEmpty()) {
            wxBindManager.bind(appKey, phone, openId, passenger.getId()); // 绑定该用户
        }
        dataMap.put("passenger", passenger);
        return dataMap;
    }

    /************************************************************************************************************
     *
     * 初始化数据
     *
     ************************************************************************************************************/

    /**
     * 获取用户进入页面时的加载信息
     *
     * @param passengerId 用户ID 非必须
     * @param appKey      系统key 必须
     * @param acKey       指定公司key 非必须
     * @param longitude   经度 必须
     * @param latitude    纬度 必须
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("getInitInfo")
    public ResultV5 getInitInfo(@RequestParam(required = true, value = "appKey") String appKey,
                                @RequestParam(required = false, value = "passengerId") Long passengerId,
                                @RequestParam(required = false, value = "acKey") String acKey,
                                @RequestParam(required = false, value = "longitude") Double longitude,
                                @RequestParam(required = false, value = "latitude") Double latitude) throws Exception {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        // 如果是用户登陆后来刷新配置数据，则查询他的真实公司
        Long passengerCompanyId = null;
        if (null != passengerId) {
            Passenger passenger = passengerApi.findById(passengerId, appKey);
            if (null != passenger) {
                passengerCompanyId = passenger.getCompanyId();
            }
        }

        // 获取该公司的业务
        JSONObject services = daijiaApi.getServices(server);

        // 调用接口获取公司id名称,电话，服务价格（feeContent），服务人员服务协议（agreementEmploy），服务协议（agreement）等
        JSONObject rsInfo = daijiaApi.getCompanyIdAndName(server, acKey, passengerCompanyId, longitude, latitude);
        Long companyId = null;
        if (null != rsInfo) {
            companyId = rsInfo.getJSONObject("data").getLong("companyId");
        }

        // 获取该公司对应业务的广告banner
        Map<String, Object> serviceMap = new LinkedHashMap<String, Object>();
        if (null != services) {

            boolean daijia = services.getBoolean("daijia");
            boolean zhuanche = services.getBoolean("zhuanche");
            boolean zuche = services.getBoolean("zuche");
            boolean paotui = services.getBoolean("paotui");
            // boolean partner = services.getBoolean("partner");
            boolean freight = services.getBoolean("freight");
            boolean zhuanxian = services.getBoolean("zhuanxian");
            boolean gasstation = services.getBoolean("gasstation");

            Map<String, Object> daijiaMap = new HashMap<String, Object>();
            Map<String, Object> zhuancheMap = new HashMap<String, Object>();
            Map<String, Object> zucheMap = new HashMap<String, Object>();
            Map<String, Object> paotuiMap = new HashMap<String, Object>();
            Map<String, Object> freightMap = new HashMap<String, Object>();
            Map<String, Object> zhuanxianMap = new HashMap<String, Object>();
            Map<String, Object> gasstationMap = new HashMap<String, Object>();

            daijiaMap.put("isopen", daijia);
            zhuanxianMap.put("isopen", zhuanxian);
            zhuancheMap.put("isopen", zhuanche);
            zucheMap.put("isopen", zuche);
            paotuiMap.put("isopen", paotui);
            freightMap.put("isopen", freight);
            gasstationMap.put("isopen", gasstation);

            // banner图和跑腿以及其他业务的数据到底取哪家公司的加载
            Long realCompanyId = null; // 这是最后要加载的公司的ID
            if (null != companyId) {
                realCompanyId = companyId;
            } else {
                realCompanyId = passengerCompanyId;
            }

            // 如果还是没有取到，默认主公司
            if (null == realCompanyId) {
                JSONObject mainCompany = daijiaApi.getMianCompany(server);
                if (null == mainCompany) {
                    return ErrorMapV5.ERR_GET_COMPANY;
                }
                realCompanyId = mainCompany.getLong("id");
            }
            /**daijia项目没有配置module.api.url,所有屏蔽获取广告位*/
//            if (daijia) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "daijia", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    daijiaMap.put("banner", rs.getData());
//                }
//            }
//
//            if (zhuanche) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "zhuan", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    zhuancheMap.put("banner", rs.getData());
//                }
//            }
//
//            if (zuche) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "zu", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    zucheMap.put("banner", rs.getData());
//                }
//            }
//
//            if (paotui) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "pao", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    paotuiMap.put("banner", rs.getData());
//                }
//
//                // 有跑腿业务，获取跑腿业务的自业务类型
//                ResultTransport resultTransport = errandManager.queryTypeV4(realCompanyId, null, appKey);
//                if (resultTransport.getCode() == 0) {
//                    paotuiMap.put("services", resultTransport.getData());
//                } else {
//                    paotuiMap.put("services", "暂时不能获取任务类型");
//                }
//            }
//
//            if (freight) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "freight", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    freightMap.put("banner", rs.getData());
//                }
//            }
//
//            if (zhuanxian) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "zhuanxian", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    zhuanxianMap.put("banner", rs.getData());
//                }
//            }
//
//            if (gasstation) {
//                ResultV5 rs = newsService.getNewsListByServiceType(realCompanyId, "gasstation", appKey);
//                if (null != rs && (rs.getCode() == 0 || rs.getCode().equals(0))) {
//                    gasstationMap.put("banner", rs.getData());
//                }
//            }

            // 根据不同的系统key，调换菜单位置
            switch (appKey) {
                // 跑D快：修改货运和城际专线的位置，专线在前，货运在后
                case "e52f83e0d37d4b8e9e3756c874365ac3":
                    serviceMap.put("daijia", daijiaMap);
                    serviceMap.put("zhuanche", zhuancheMap);
                    serviceMap.put("zuche", zucheMap);
                    serviceMap.put("paotui", paotuiMap);
                    serviceMap.put("zhuanxian", zhuanxianMap);
                    serviceMap.put("freight", freightMap);
                    serviceMap.put("gasstation", gasstationMap);
                    break;

                // 鹭捷：修改货运和城际专线的位置，专线在前，货运在后
                case "8ed5f3ec7af74469a689c363918b9850":
                    serviceMap.put("freight", freightMap);
                    serviceMap.put("daijia", daijiaMap);
                    serviceMap.put("zhuanche", zhuancheMap);
                    serviceMap.put("zuche", zucheMap);
                    serviceMap.put("paotui", paotuiMap);
                    serviceMap.put("zhuanxian", zhuanxianMap);
                    serviceMap.put("gasstation", gasstationMap);
                    break;

                // 默认顺序
                default:
                    serviceMap.put("zhuanxian", zhuanxianMap);
                    serviceMap.put("daijia", daijiaMap);
                    serviceMap.put("zhuanche", zhuancheMap);
                    serviceMap.put("zuche", zucheMap);
                    serviceMap.put("paotui", paotuiMap);
                    serviceMap.put("freight", freightMap);
                    serviceMap.put("gasstation", gasstationMap);
                    break;
            }
        }

        // 获取APP设置
        JSONObject appSetting = daijiaApi.getAppSettingV5(server);

        // 获取支付设置
        JSONObject paySetting = daijiaApi.getPaySettingV5(server);

        // 集中数据
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("services", serviceMap);
        data.put("appSetting", appSetting);
        data.put("paySetting", paySetting);
        data.put("companyInfo", rsInfo);
        // 代驾地址
        data.put("daijiaServer", server);
        data.put("wxQrCode", null);
        /*try {
            String qrCode = daijiaApi.getWxQrCode(server);
            if (StringUtils.isNotBlank(qrCode)) {
                qrCode = server + "/" + qrCode;
                // 微信二维码
                data.put("wxQrCode", qrCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        // 返回数据
        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(data);
        return result;
    }

    /************************************************************************************************************
     *
     * 更新信息
     *
     ************************************************************************************************************/

    /**
     * 更新用户信息：<br>
     * 注：客户更新头像请调用代驾接口：daijiaServer/api/passenger/uploadPhoto
     *
     * @param appKey    系统Key
     * @param name      姓名
     * @param gender    性别
     * @param phone     电话
     * @param memberEcn 紧急联系人
     * @param memberEcp 紧急电话
     * @param address   常用目的地
     * @param lat       常用目的地lat
     * @param lng       常用目的地lng
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "update", method = {RequestMethod.POST})
    public ResultV5 updatePassengerInfo(@RequestParam(value = "appKey", required = true) String appKey,
                                        @RequestParam(value = "phone", required = true) String phone,
                                        @RequestParam(value = "name", required = false) String name,
                                        @RequestParam(value = "gender", required = false) Integer gender,
                                        @RequestParam(value = "memberEcn", required = false) String memberEcn,
                                        @RequestParam(value = "memberEcp", required = false) String memberEcp,
                                        @RequestParam(value = "address", required = false) String address,
                                        @RequestParam(value = "lat", required = false) Double lat,
                                        @RequestParam(value = "lng", required = false) Double lng) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        boolean isUpdate = daijiaApi.updatePassengerInfoV5(server, phone, appKey, name, gender, memberEcn, memberEcp,
                address, lat, lng);
        if (isUpdate) {
            return ErrorMapV5.ERR_SUCCESS.clone();
        } else {
            return ErrorMapV5.ERR_UPDATE_PASSENGER_FAILD;
        }
    }

    /************************************************************************************************************
     *
     * 我的订单
     *
     ************************************************************************************************************/

    /**
     * 获取各业务订单
     *
     * @param serviceType 业务类型名称
     * @param appKey      系统key
     * @param passengerId 乘客id
     * @param page        页码
     * @param rows        数据量
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getOrders", method = {RequestMethod.GET})
    public ResultV5 getOrders(String serviceType, String appKey, Long passengerId, Integer page, Integer rows) {

        // 业务类型列表
        String[] types = {"paotui", "daijia", "zhuanche", "zhuanxian", "jiayouzhan"};

        // 排除没有在列表中的业务
        if (!Arrays.asList(types).contains(serviceType)) {
            return ErrorMapV5.ERR_PARAMS;
        }

        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        if (null == wxApplication) {
            return new ResultV5(-1, "无该应用");
        }
        String server = wxApplication.getAddress();
        if (null == server || server.isEmpty()) {
            return new ResultV5(-1, "无效的代驾服务地址");
        }

        // 匹配业务
        switch (serviceType) {

            // 跑腿
            case "paotui":
                try {
                    DataGrid<Map<String, Object>> list = errandManager.findOrderV2(passengerId, page - 1, rows, appKey,
                            server);
                    result.setData(list);
                } catch (Exception e) {
                    e.printStackTrace();
                    return ErrorMapV5.ERR_GET_PAO_ORDER;
                }
                break;

            // 代驾
            case "daijia":
                try {
                    Map<String, Object> data = daijiaApi.getOrdersV5(server, passengerId, page, rows);
                    result.setData(data);
                } catch (Exception e) {
                    e.printStackTrace();
                    return ErrorMapV5.ERR_GET_DAIJIA_ORDER;
                }
                break;

            // 专车
            case "zhuanche":
                try {
                    Map<String, Object> data = zhuanApi.getOrdersV5(passengerId, page, rows, "uncancel", appKey);
                    result.setData(data);
                } catch (Exception e) {
                    e.printStackTrace();
                    // return ErrorMapV5.ERR_GET_ZHUANCHE_ORDER;
                }
                break;

            // 专线
            case "zhuanxian":
                try {
                    Map<String, Object> data = zhuanXianApi.getOrdersV5(passengerId, page, rows, appKey);
                    result.setData(data);
                } catch (Exception e) {
                    e.printStackTrace();
                    // return ErrorMapV5.ERR_GET_ZHUANXIAN_ORDER;
                }
                break;

            // 加油站
            case "jiayouzhan":
                try {
                    // Map<String, Object> data = new HashMap<String, Object>();
                    ResultV5 rs = gasApi.orders(passengerId, page, rows, appKey);
                    result.setData(rs.getData());
                } catch (Exception e) {
                    e.printStackTrace();
                    return ErrorMapV5.GET_GAS_ORDERS_ERR;
                }
                break;
            default:
                break;
        }
        return result;
    }

    /**
     * 获取各业务未完成未支付的订单
     *
     * @param appKey      系统key
     * @param passengerId 客户ID
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getNotSuccessOrders", method = {RequestMethod.GET})
    public ResultV5 getNotSuccessOrders(@RequestParam(required = true, value = "appKey") String appKey,
                                        @RequestParam(required = true, value = "passengerId") Long passengerId) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        Map<String, Object> dataMap = new LinkedHashMap<String, Object>();

        final String DAIJIA = "daijia";
        final String PAOTUI = "paotui";
        final String ZHUANCHE = "zhuanche";
        final String ZHUANXIAN = "zhuanxian";

        // 获取专车未完成订单
        try {
            JSONArray zhuancheNotSuccessOrders = zhuanApi.findRunning(passengerId, appKey);
            dataMap.put(ZHUANCHE, zhuancheNotSuccessOrders);
        } catch (Exception e) {
            e.printStackTrace();
            dataMap.put(ZHUANCHE, null);
        }

        // 获取跑腿未完成订单
//        try {
//            JSONArray paotuiNotSuccessOrders = errandApi.findRunning(passengerId, appKey);
//            dataMap.put(PAOTUI, paotuiNotSuccessOrders);
//        } catch (Exception e) {
//            e.printStackTrace();
//            dataMap.put(PAOTUI, null);
//        }

        // 获取代驾未完成订单

        try {
            JSONArray daijiaNotSuccessOrders = daijiaApi.findRunningV5(server, passengerId);
            dataMap.put(DAIJIA, daijiaNotSuccessOrders);
        } catch (Exception e) {
            e.printStackTrace();
            dataMap.put(DAIJIA, null);
        }

        // 获取专线未完成订单
        try {
            JSONArray zhuanxianNotSuccessOrders = zhuanXianApi.findRunning(passengerId, appKey);
            dataMap.put(ZHUANXIAN, zhuanxianNotSuccessOrders);
        } catch (Exception e) {
            e.printStackTrace();
            dataMap.put(ZHUANXIAN, null);
        }

        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(dataMap);
        return result;
    }

    /************************************************************************************************************
     *
     * 我的钱包
     *
     ************************************************************************************************************/

    /**
     * 获取乘客信息,余额信息在里面
     *
     * @param passengerId
     * @param appKey
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getPassengerInfo", method = {RequestMethod.GET})
    public ResultV5 getBalance(@RequestParam(required = true, value = "appKey") String appKey,
                               @RequestParam(required = true, value = "passengerId") Long passengerId) {

        Passenger passenger = passengerApi.findById(passengerId, appKey);

        if (null == passenger) {
            return ErrorMapV5.ERR_PASSENGER_IS_EMPTY;
        }

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        // 获取用户常用目的地地址,紧急联系人
        JSONObject data = daijiaApi.getPassengerEcnEcpAndAddress(server, appKey, passenger.getId());
        passenger.setOther(data);

        ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
        result.setData(passenger);
        return result;
    }

    /**
     * 充值余额
     *
     * @param appId       微信应用ID
     * @param appKey      系统Key
     * @param passengerId 客户ID
     * @param money       金额
     * @param openId      微信openId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "addbalance", method = {RequestMethod.POST})
    public ResultV5 rechargeBalance(HttpServletRequest request,
                                    @RequestParam(required = true, value = "appId") String appId,
                                    @RequestParam(required = true, value = "appKey") String appKey,
                                    @RequestParam(required = true, value = "passengerId") Long passengerId,
                                    @RequestParam(required = true, value = "money") BigDecimal money,
                                    @RequestParam(required = true, value = "openId") String openId) {

        try {
            WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
            WxAccount wxAccount = wxAccountManager.findBy(appId, wxApplication.getId());
            String server = wxApplication.getAddress();

            // 判断是否来自微信
            StringBuilder sb = new StringBuilder();
            sb.append(request.getScheme());
            sb.append("://");
            sb.append(request.getServerName());
            int port = request.getServerPort();
            if (port != 80) {
                sb.append(":").append(port);
            }
            sb.append(request.getRequestURI());
            String queryString = request.getQueryString();
            if (StringUtils.isNotBlank(queryString)) {
                sb.append("?");
                sb.append(queryString);
            }

            JSONObject json = daijiaApi.addbalance(server, passengerId, money, openId);

            ResultV5 result = null;
            JSONObject data = new JSONObject();
            if (null != json) {
                JSONObject rs = json.getJSONObject("data");
                data.put("package", rs.getString("package"));
                data.put("timestamp", rs.getString("timeStamp"));
                data.put("url", sb.toString());
                data.put("nonceStr", rs.getString("nonceStr"));
                data.put("paySign", rs.getString("sign"));

                // 获取微信AccessToken
                String response = restTemplate.getForObject(WX_ACCESS_TOKEN, String.class, wxAccount.getWxappId(),
                        wxAccount.getAppsecret());
                JSONObject ac = JSON.parseObject(response);
                if (ac.containsKey("access_token")) {
                    String accessToken = ac.getString("access_token"); // 获取微信access_token
                    String resp = restTemplate.getForObject(WX_JSAPI_TICKET, String.class, accessToken); // 获取jsapi_ticket
                    JSONObject ticketJson = JSON.parseObject(resp);
                    if (ticketJson.containsKey("ticket")) {
                        String ticket = ticketJson.getString("ticket");
                        data.put("jsapi_ticket", ticket);
                        Map<String, Object> signParams = new HashMap<>();
                        signParams.put("jsapi_ticket", ticket);
                        signParams.put("timestamp", rs.getString("timeStamp"));
                        signParams.put("url", sb.toString());
                        signParams.put("noncestr", rs.getString("nonceStr"));
                        data.put("signature", WxUtils.buildSha1Sign(signParams));

                        result = ErrorMapV5.ERR_SUCCESS.clone();
                        result.setData(data);
                        return result;
                    }
                }
            } else {
                return ErrorMapV5.ERR_ADD_BALANCE;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ErrorMapV5.ERR_SYSTEM;
        }
        return ErrorMapV5.ERR_GET_WECHAT_PAY_PARAMS;
    }

    /**
     * 获取资金流水记录(分页)
     *
     * @param phone  电话
     * @param page   页码
     * @param rows   条数
     * @param appKey 系统key
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "capitalRecords", method = {RequestMethod.GET})
    public ResultV5 capitalRecords(@RequestParam(required = true, value = "phone") String phone,
                                   @RequestParam(required = true, value = "page") Integer page,
                                   @RequestParam(required = true, value = "rows") Integer rows,
                                   @RequestParam(required = true, value = "appKey") String appKey) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.capitalRecordsV5(server, phone, page, rows, null);
    }

    /**
     * 获取资金流水详情
     *
     * @return
     */
    // @ResponseBody
    // @RequestMapping(value="capitalDetails", method={RequestMethod.GET})
    // public ResultV5 capitalDetails () {
    //
    // return null;
    // }

    /************************************************************************************************************
     *
     * 优惠券
     *
     ************************************************************************************************************/

    /**
     * 获取优惠卷，包括未使用的，已使用的，已过期的
     *
     * @param phone  乘客电话
     * @param page   页码
     * @param rows   条数
     * @param appKey 系统Key
     * @param status 优惠券状态 0未绑定 1未用(已绑定) 2已用 3失效
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getCoupons", method = {RequestMethod.GET})
    public ResultV5 getCoupons(@RequestParam(required = true, value = "phone") String phone,
                               @RequestParam(required = true, value = "page") Integer page,
                               @RequestParam(required = true, value = "rows") Integer rows,
                               @RequestParam(required = true, value = "appKey") String appKey,
                               @RequestParam(required = false, value = "status") Integer status) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.getCouponsV5(server, phone, page - 1, rows, status);
    }

    /**
     * 添加优惠券
     *
     * @param phone   电话
     * @param code    优惠券号
     * @param codeKey 优惠券密码
     * @param appKey  系统Key
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "addCoupons", method = {RequestMethod.POST})
    public ResultV5 addCoupons(@RequestParam(required = true, value = "phone") String phone,
                               @RequestParam(required = true, value = "code") String code,
                               @RequestParam(required = true, value = "codeKey") String codeKey,
                               @RequestParam(required = true, value = "appKey") String appKey) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.couponsBindV5(server, phone, code, codeKey);
    }

    /**
     * 申请发票
     *
     * @param appKey 系统Key
     * @param phone  电话
     * @param money  金额
     * @param type   类型
     * @param memo   备注
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "applyInvoice", method = {RequestMethod.POST})
    public ResultV5 applyInvoice(@RequestParam(required = true, value = "appKey") String appKey,
                                 @RequestParam(required = true, value = "phone") String phone,
                                 @RequestParam(required = true, value = "money") BigDecimal money,
                                 @RequestParam(required = true, value = "type") String type,
                                 @RequestParam(required = false, value = "memo") String memo) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.createReceiptV5(server, phone, appKey, money, type, memo);
    }

    /**
     * 获取发票申请记录
     *
     * @param appKey 系统key
     * @param phone  电话
     * @param page   页码
     * @param rows   条数
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "applyInvoiceRecords", method = {RequestMethod.POST})
    public ResultV5 applyInvoiceRecords(@RequestParam(required = true, value = "appKey") String appKey,
                                        @RequestParam(required = true, value = "phone") String phone,
                                        @RequestParam(required = true, value = "page") Integer page,
                                        @RequestParam(required = true, value = "rows") Integer rows) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.queryReceiptV5(server, appKey, phone, page, rows);
    }

    /************************************************************************************************************
     *
     * 设置中心
     *
     ************************************************************************************************************/

    /**
     * 服务价格，初始化时已携带返回，这里注释不需要了
     *
     * @return
     */
    // @ResponseBody
    // @RequestMapping(value="servicePrice", method={RequestMethod.GET})
    // public ResultV5 servicePrice (String appKey, String acKey, Long companyId,
    // Double lat, Double lng) {
    //
    // WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    // String server = wxApplication.getAddress();
    //
    // JSONObject json = daijiaApi.getCompanyIdAndName(server, acKey, companyId,
    // lng, lat);
    // ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
    // result.setData(json.getJSONObject("data").getString("feeContent"));
    // return result;
    // }

    /**
     * 服务协议，初始化时已携带返回，这里注释不需要了
     *
     * @return
     */
    // @ResponseBody
    // @RequestMapping(value="serviceAgreement", method={RequestMethod.GET})
    // public ResultV5 serviceAgreement (
    // @RequestParam(required = true, value = "appKey") String appKey,
    // @RequestParam(required = false, value = "acKey") String acKey,
    // @RequestParam(required = true, value = "companyId") Long companyId,
    // @RequestParam(required = false, value = "lat") Double lat,
    // @RequestParam(required = false, value = "lng") Double lng) {
    //
    // WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    // String server = wxApplication.getAddress();
    // JSONObject json = daijiaApi.getCompanyIdAndName(server, acKey, companyId,
    // lng, lat);
    // ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
    // result.setData(json.getJSONObject("data").getString("agreement"));
    // return result;
    // }

    /**
     * 注销账户
     *
     * @param appKey 系统
     * @param phone  电话
     * @param openId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "logout", method = {RequestMethod.POST})
    public ResultV5 logout(String appKey, String phone, String openId) {
        Passenger passenger = passengerApi.findOne(phone, appKey);
        if (null == passenger) {
            return ErrorMapV5.ERR_SUCCESS.clone();
        }
        try {
            wxBindManager.debind(appKey, phone, openId);
            return ErrorMapV5.ERR_SUCCESS.clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ErrorMapV5.ERR_LOGOUT_V5;
    }

    /************************************************************************************************************
     *
     * 消息通知
     *
     ************************************************************************************************************/

    /**
     * 微信公众号V5分页获取通知
     *
     * @param appKey      系统KEY
     * @param passengerId 乘客ID
     * @param page        页码
     * @param rows        条数
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getNotice", method = {RequestMethod.GET})
    public ResultV5 getNotice(@RequestParam(required = true, value = "appKey") String appKey,
                              @RequestParam(required = true, value = "passengerId") Long passengerId,
                              @RequestParam(required = true, value = "page") Integer page,
                              @RequestParam(required = true, value = "rows") Integer rows) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.getNoticeV5(server, passengerId, page, rows);
    }

    /**
     * 获取用户未读通知
     *
     * @param appKey      系统key
     * @param passengerId 客户ID
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getNotReadNotices", method = {RequestMethod.GET})
    public ResultV5 getNotReadNotices(@RequestParam(required = true, value = "appKey") String appKey,
                                      @RequestParam(required = true, value = "passengerId") Long passengerId) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        JSONObject rs = daijiaApi.getNotReadNoticesV5(server, passengerId);
        if (null == rs || rs.isEmpty()) {
            return ErrorMapV5.ERR_GET_NOT_READ_NOTICES;
        }

        int code = rs.getIntValue("code");
        if (code == 0) {
            ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
            String ids = String.valueOf(rs.get("data")).replace("[", "").replace("]", "").replaceAll(" ", "");
            result.setData(ids);
            return result;
        }

        return ErrorMapV5.ERR_GET_NOT_READ_NOTICES;
    }

    /**
     * 更新通知已读
     *
     * @param appKey      系统KEY
     * @param passengerId 乘客ID
     * @param noticeIds   通知ID，逗号分隔
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "updateNoticeRead", method = {RequestMethod.POST})
    public ResultV5 updateNoticeRead(@RequestParam(required = true, value = "appKey") String appKey,
                                     @RequestParam(required = true, value = "passengerId") Long passengerId,
                                     @RequestParam(required = true, value = "noticeIds") String noticeIds) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        String[] nids = noticeIds.split(",");

        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.execute(new NoticeWorker(server, nids, passengerId, daijiaApi));
        return ErrorMapV5.ERR_SUCCESS.clone();
    }

    /**
     * 微信V5获取通知详情
     *
     * @param appKey      系统KEY
     * @param passengerId 乘客ID
     * @param noticeId    通知ID
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "noticeInfo", method = {RequestMethod.POST})
    public ResultV5 noticeInfo(@RequestParam(required = true, value = "appKey") String appKey,
                               @RequestParam(required = true, value = "passengerId") Long passengerId,
                               @RequestParam(required = true, value = "noticeId") Long noticeId) {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();
        return daijiaApi.getNoticeInfoV5(server, passengerId, noticeId);
    }

    /************************************************************************************************************
     *
     * 推荐有奖
     *
     ************************************************************************************************************/

    /**
     * 获取乘客二维码
     *
     * @param appKey
     * @param acKey
     * @param passengerId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getQrCode", method = {RequestMethod.GET})
    public ResultV5 getQrCode(@RequestParam(required = true, value = "appKey") String appKey,
                              @RequestParam(required = false, value = "acKey") String acKey,
                              @RequestParam(required = true, value = "passengerId") Long passengerId) throws Exception {

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        Map<String, Object> map = daijiaApi.getQrCodeData(server, passengerId, acKey);

        ResultV5 result = null;

        // 获取失败
        if (Integer.parseInt(String.valueOf(map.get("code"))) != 0) {
            result = ErrorMapV5.ERR_GET_QR_CODE;
            return result;
        }

        // 获取成功
        if (Integer.parseInt(String.valueOf(map.get("code"))) == 0) {

            // 获取生产二维码需要的数据
            JSONObject json = JSONObject.parseObject(JsonUtil.stringify(map.get("data")));
            String shareUrl = json.getString("shareUrl") == null ? "" : json.getString("shareUrl");
            String qrLogo = json.getString("qrLogo") == null ? "" : json.getString("qrLogo");
            server = server.endsWith("/") ? server : server + "/";
            server = (!server.startsWith("http://")) ? ("http://" + server) : server;

            // 生成二维码，保存到项目根的/qrcode/appKey.png
            try {
                String path = Thread.currentThread().getContextClassLoader().getResource("").getFile();
                String fileDir = "qrcode/";
                String saveDir = path + "../../" + fileDir;

                // 下载logo到本地
                String logoPath = null;
                String logoName = null;
                if (qrLogo != "") {
                    logoName = qrLogo.substring(qrLogo.lastIndexOf("/") + 1, qrLogo.length());
                    String logoType = qrLogo.substring(qrLogo.lastIndexOf(".") + 1, qrLogo.length());
                    File logoFile = new File(saveDir + logoName + logoType);
                    if (!logoFile.exists()) {
                        try {
                            logoPath = HttpClient.DownloadByUrl((server + qrLogo), saveDir, logoName, logoType);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                            logoPath = null;
                        }
                    }
                }

                // 生成二维码
                SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
                String file = appKey + "_" + passengerId + "_" + df.format(new Date()) + ".png";
                String savePath = saveDir + file;
                QRCodeUtil.encode((server + shareUrl), logoPath, savePath, 500);
                json.put("qrCode", fileDir + file);
            } catch (Exception e) {
                e.printStackTrace();
                result = ErrorMapV5.ERR_GET_QR_CODE;
            }

            result = ErrorMapV5.ERR_SUCCESS.clone();
            result.setData(json);
        }
        return result;
    }

    /**
     * 推荐记录
     *
     * @param passengerId 客户ID
     * @param page        页码
     * @param rows        条数
     * @param appKey      系统Key
     * @param payType     支付类型 （返利传："RECHARGE_TYPE_REBATE"）
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "recommendRecord", method = {RequestMethod.GET})
    public ResultV5 recommendRecord(@RequestParam(required = true, value = "passengerId") Long passengerId,
                                    @RequestParam(required = true, value = "page") Integer page,
                                    @RequestParam(required = true, value = "rows") Integer rows,
                                    @RequestParam(required = true, value = "appKey") String appKey,
                                    @RequestParam(required = true, value = "payType") String payType) {

        ResultV5 result = null;

        WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
        String server = wxApplication.getAddress();

        // 获取推荐返利
        JSONObject json = daijiaApi.getRecommendRebateByPassenger(server, passengerId, payType, page - 1, rows);
        if (null != json && json.getBooleanValue("success")) {
            result = ErrorMapV5.ERR_SUCCESS.clone();
            result.setData(json);
        } else {
            result = ErrorMapV5.ERR_GET_RECOMMEND_RECORD;
        }
        return result;
    }
}
